import Koa from 'koa';
import koaBody from 'koa-body';
import cors from '@koa/cors';
import helmet from 'koa-helmet';
import { config } from '@/config';
import { logger } from '@/utils/logger';
import { closeDatabases } from '@/databases';
import { initializeRoutes } from '@/routes';
import {
  errorHandler,
  notFoundHandler,
  requestLogger,
  responseTime,
  requestId,
  securityHeaders,
  initializeSwagger,
} from '@/middlewares';

/**
 * 应用程序类
 */
export class App {
  private app: Koa;
  private server: any;

  constructor() {
    this.app = new Koa();
    this.setupMiddlewares();
    this.setupRoutes();
    this.setupErrorHandling();
  }

  /**
   * 设置中间件
   */
  private setupMiddlewares(): void {
    // 错误处理中间件（必须放在最前面）
    this.app.use(errorHandler);

    // 安全相关中间件
    this.app.use(helmet({
      contentSecurityPolicy: {
        directives: {
          defaultSrc: ["'self'"],
          scriptSrc: [
            "'self'",
            "'unsafe-inline'", // Swagger UI 需要
            "https://cdnjs.cloudflare.com",
            "https://cdn.jsdelivr.net",
            "https://unpkg.com"
          ],
          styleSrc: [
            "'self'",
            "'unsafe-inline'", // Swagger UI 需要
            "https://fonts.googleapis.com",
            "https://cdnjs.cloudflare.com",
            "https://cdn.jsdelivr.net",
            "https://unpkg.com"
          ],
          fontSrc: [
            "'self'",
            "https://cdnjs.cloudflare.com",
            "https://fonts.gstatic.com"
          ],
          imgSrc: [
            "'self'",
            "data:",
            "https:"
          ],
          connectSrc: ["'self'"],
        },
      },
    }));
    this.app.use(securityHeaders);

    // 请求处理中间件
    this.app.use(responseTime);
    this.app.use(requestId);
    this.app.use(requestLogger);

    // CORS 配置
    this.app.use(cors({
      origin: config.cors.origin,
      credentials: config.cors.credentials,
      allowHeaders: ['Content-Type', 'Authorization', 'Accept', 'X-Request-ID'],
      allowMethods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'],
      maxAge: 86400, // 24小时
    }));

    // 请求体解析
    this.app.use(koaBody({
      multipart: true,
      formidable: {
        maxFileSize: 10 * 1024 * 1024, // 10MB
        maxFieldsSize: 2 * 1024 * 1024, // 2MB
        maxFields: 100,
        keepExtensions: true,
      },
      onError: (error, ctx) => {
        logger.error(error, '请求体解析错误');
        ctx.throw(400, '请求体解析失败');
      },
    }));
  }

  /**
   * 设置路由
   */
  private setupRoutes(): void {
    // Swagger 文档中间件
    const swaggerMiddlewares = initializeSwagger();
    swaggerMiddlewares.forEach(middleware => {
      this.app.use(middleware);
    });

    // 初始化路由
    initializeRoutes(this.app);

    // 404 处理中间件（必须放在路由后面）
    this.app.use(notFoundHandler);
  }

  /**
   * 设置错误处理
   */
  private setupErrorHandling(): void {
    // 应用级错误事件监听
    this.app.on('error', (error, ctx) => {
      logger.error({
        error: {
          message: error.message,
          stack: error.stack,
          status: error.status || 500,
        },
        request: ctx ? {
          method: ctx.method,
          url: ctx.url,
          headers: ctx.headers,
          ip: ctx.ip,
        } : null,
      }, '应用错误');
    });

    // 进程级错误处理
    process.on('uncaughtException', (error) => {
      logger.fatal(error, '未捕获的异常');
      this.gracefulShutdown('uncaughtException');
    });

    process.on('unhandledRejection', (reason, promise) => {
      logger.fatal({
        reason,
        promise,
      }, '未处理的 Promise 拒绝');
      this.gracefulShutdown('unhandledRejection');
    });

    // 优雅关闭信号处理
    process.on('SIGTERM', () => {
      logger.info('收到 SIGTERM 信号');
      this.gracefulShutdown('SIGTERM');
    });

    process.on('SIGINT', () => {
      logger.info('收到 SIGINT 信号');
      this.gracefulShutdown('SIGINT');
    });
  }

  /**
   * 启动应用
   */
  public async start(): Promise<void> {
    try {
      // 初始化数据库
      // await this.initializeDatabases();

      // 启动 HTTP 服务器
      this.server = this.app.listen(config.app.port, () => {
        logger.info({
          port: config.app.port,
          env: config.app.env,
          pid: process.pid,
          version: config.app.version,
        }, `🚀 服务器启动成功`);

        // 在开发环境下显示可用的端点
        if (config.app.env === 'development') {
          this.logAvailableEndpoints();
        }
      });

      // 设置服务器超时
      this.server.timeout = 30000; // 30秒
      this.server.keepAliveTimeout = 65000; // 65秒
      this.server.headersTimeout = 66000; // 66秒

    } catch (error) {
      logger.error(error, '应用启动失败');
      process.exit(1);
    }
  }

  /**
   * 优雅关闭
   */
  private async gracefulShutdown(signal: string): Promise<void> {
    logger.info(`开始优雅关闭应用... (信号: ${signal})`);

    try {
      // 停止接受新连接
      if (this.server) {
        this.server.close(() => {
          logger.info('HTTP 服务器已关闭');
        });
      }

      // 关闭数据库连接
      await closeDatabases();

      logger.info('应用已成功关闭');
      process.exit(0);
    } catch (error) {
      logger.error(error, '应用关闭过程中发生错误');
      process.exit(1);
    }
  }

  /**
   * 记录可用的端点
   */
  private logAvailableEndpoints(): void {
    const baseUrl = `http://localhost:${config.app.port}`;
    
    logger.info('📋 可用的端点:');
    logger.info(`   健康检查:     ${baseUrl}/health`);
    logger.info(`   API 根目录:   ${baseUrl}/api`);
    logger.info(`   API v1:       ${baseUrl}/api/v1`);
    logger.info(`   用户 API:     ${baseUrl}/api/v1/users`);
    
    if (config.swagger.enabled) {
      logger.info(`   API 文档:     ${baseUrl}${config.swagger.path}`);
    }
  }

  /**
   * 获取应用实例
   */
  public getApp(): Koa {
    return this.app;
  }

  /**
   * 获取服务器实例
   */
  public getServer(): any {
    return this.server;
  }
}

/**
 * 应用实例
 */
const application = new App();

/**
 * 启动应用（仅在直接运行此文件时）
 */
if (require.main === module) {
  application.start().catch((error) => {
    logger.fatal(error, '应用启动失败');
    process.exit(1);
  });
}

export default application;
export { App as Application };